$: << File.join(File.expand_path(File.dirname(__FILE__)), "..")
#===============================
# Implements basic numeric functions:
# Count: Count number of times a key appears
# Count+: Count how often value is greater than zero
# Count-: Count how often value is less than zero
# Count0: Count how often value is equal to zero
# Sum: Do sum of values
#==============================
require 'rubygems'
require 'optparse'
require 'EasyHadoop'

# Define Class
class Stat < EasyHadoop
	
  @@OPERATIONS = ["count", "count+", "count-", "count0", "sum"]
  attr_reader :key, :values

  #constructor
	def initialize(arguments)
		super(arguments)
	
		@key = nil
		@values = []
	end
  
	def set_mandatory
		super
		@mandatory << :operations
	end
	
	def set_commands
		super
		@optparse.banner = "Usage: ruby #{File.basename(__FILE__)} --operations=METHOD1,METHOD2,METHOD3.."
		
		@options[:operations] = nil
        @optparse.on('-o OPERATIONS', '--operations LIST', "Possible operations are #{@@OPERATIONS.join(', ')}" ) do |hypo|
        	@options[:operations]=[] unless @options[:operations]
			hypo.split(",").each{|h|
				h = h.to_s.strip.downcase()
				raise OptionParser::InvalidOption, "Invalid Operation: #{h}" unless @@OPERATIONS.include?(h)
				@options[:operations] << h
			}	
			@options[:operations] = @options[:operations].uniq
        end	

	end

  	def execute(line)
		return nil if line.nil? or line.to_s.strip().length == 0
		key, value = line.to_s.chomp.split(@options[:input_delimiter])

		#Sanity Checks
		return nil if key == nil or key.to_s.strip().length == 0

		key = key.to_s.strip()
		value = value.to_f unless value.nil?

		if(key != @key)
			yield print 
			@key = key
			@values = []
		end
		@values << value   
	end
  
  	def print
	  	return nil if @key == nil or @values.length == 0
	  	opt = {}
	  	@options[:operations].each{|o| opt[o]=0.0}
	  	opt['count'] = @values.length if @options[:operations].include?('count')
	  	@values.each{|v|
	  		next if(v.nil?)
	  		@options[:operations].each{|o|
	  			opt[o]=opt[o]+1 if o=="count+" and v > 0
	  			opt[o]=opt[o]+1 if o=="count-" and v < 0
	  			opt[o]=opt[o]+1 if o=="count0" and v == 0
	  			opt[o]=opt[o]+v if o=="sum"
	  		}	
	  	}

	  	tmp = []
	  	tmp << @key
	  	@options[:operations].each{|o| tmp << opt[o] }
	  	return tmp.join(@options[:output_delimiter])
	  end
  
end

# Scripting Option
if __FILE__ == $0
	cls = Stat.new(ARGV)
    STDIN.each_line{|line|
	  cls.execute(line) {|value|
      	puts value unless value.nil?
      }
	}
end
